/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package at.irian.web.jsf.orchestra;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

/**
 * @author Manfred Geiler
 */
public class LastViewIdRecordingPhaseListener implements PhaseListener
{
    private static final long serialVersionUID = -404784913891323122L;

    public void beforePhase(PhaseEvent event)
    {
        //do nothing
    }

    public void afterPhase(PhaseEvent event)
    {
        ExceptionContextAdapter exceptionContextAdapter = resolveExceptionContextAdapter(event.getFacesContext());

        //fallback
        if (exceptionContextAdapter == null)
        {
            exceptionContextAdapter = createDefaultExceptionContextAdapter();
        }

        if (!exceptionContextAdapter.isErrorPageRendered())
        {
            /*
            on multiple button click (eg. transaction warnings -> save) an
            java.net.SocketException: Connection reset by peer: socket write error may be thrown.
            The last request in the sequence (which may write to the response without SocketException)
            will then display the error page as it was rendered before by getting a SocketException
             */
            LastResponseHolder lastResponseHolder = LastResponseHolder.getCurrentInstance();
            if (lastResponseHolder != null)
            {
                lastResponseHolder.setViewRoot(event.getFacesContext().getViewRoot());
            }
        }
    }

    private ExceptionContextAdapter createDefaultExceptionContextAdapter()
    {
        return new ExceptionContextAdapter()
        {
            public boolean isErrorPageRendered()
            {
                return false;
            }
        };
    }

    private ExceptionContextAdapter resolveExceptionContextAdapter(FacesContext facesContext)
    {
        return (ExceptionContextAdapter) facesContext.getApplication().getELResolver()
                .getValue(facesContext.getELContext(), null, ExceptionContextAdapter.BEAN_NAME);
    }

    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }
}
